package com.kakarote.core.utils;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.util.TypeUtils;
import com.alicp.jetcache.Cache;
import com.alicp.jetcache.CacheLoader;
import com.alicp.jetcache.CacheManager;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.template.QuickConfig;
import com.kakarote.core.common.cache.AdminCacheKey;
import com.kakarote.core.entity.UserInfo;
import com.kakarote.core.feign.admin.entity.SimpleDept;
import com.kakarote.core.feign.admin.entity.SimpleUser;
import com.kakarote.core.feign.admin.service.AdminService;
import com.kakarote.core.redis.Redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.Duration;
import java.util.*;

/**
 * @author zhangzhiwei
 * 用户缓存相关方法
 */
@Component
@ConditionalOnClass(CacheManager.class)
@Order(1)
public class UserCacheUtil {

    /**
     * 企业信息缓存KEY
     */
    private static final String COMPANY_MANAGE_CACHE_NAME = "COMPANY:MANAGE:STATUS:";

    /**
     * 用户名称缓存key
     */
    private static final String ADMIN_USER_NAME_CACHE_NAME = "ADMIN:USER:CACHE:";

    /**
     * 部门名称缓存key
     */
    private static final String ADMIN_DEPT_NAME_CACHE_NAME = "ADMIN:DEPT:CACHE:";

    static UserCacheUtil ME;

    @PostConstruct
    public void init() {
        ME = this;
        userCache = cacheManager.getOrCreateCache(QuickConfig.newBuilder(ADMIN_USER_NAME_CACHE_NAME).cacheType(CacheType.REMOTE).expire(Duration.ofDays(3)).build());
        deptCache = cacheManager.getOrCreateCache(QuickConfig.newBuilder(ADMIN_DEPT_NAME_CACHE_NAME).cacheType(CacheType.REMOTE).expire(Duration.ofDays(3)).build());
        companyCache = cacheManager.getOrCreateCache(QuickConfig.newBuilder(COMPANY_MANAGE_CACHE_NAME).cacheType(CacheType.REMOTE).expire(Duration.ofDays(3)).build());
    }

    private Cache<Long, UserInfo> userCache;

    private Cache<Long, SimpleDept> deptCache;

    @Autowired
    private AdminService adminService;

    @Autowired
    Redis redis;

    @Autowired
    private CacheManager cacheManager;

    private Cache<Long, Boolean> companyCache;

    /**
     * 根据用户ID获取用户名列表，使用，号合并
     *
     * @param userIds userIds
     * @return data
     */
    public static <T> List<String> getUserNameList(List<T> userIds) {
        if (userIds == null || userIds.isEmpty()) {
            return Collections.emptyList();
        }
        List<String> stringList = new ArrayList<>(userIds.size());
        for (T obj : userIds) {
            Long userId = TypeUtils.castToLong(obj);
            String name = getUserName(userId);
            if (!"".equals(name)) {
                stringList.add(name);
            }
        }
        return stringList;
    }

    /**
     * 根据用户ID获取用户名
     * 如果只需要用户名，部门名称，头像等信息，使用@getSimpleUser
     *
     * @param userId 用户ID
     * @return data
     */
    public static UserInfo getUserInfo(Long userId) {
        try {
            return ME.userCache.computeIfAbsent(userId, (CacheLoader<Long, UserInfo>) key -> {
                UserInfo data = ME.adminService.getUserInfo(userId).getData();
                if (data == null) {
                    data = new UserInfo();
                }
                return data;
            });
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * 查询当前用户的权限JSON
     *
     * @return auth
     */
    public static JSONObject queryUserAuth() {
        String cacheKey = AdminCacheKey.USER_AUTH_CACHE_KET + UserUtil.getUserId();
        if (ME.redis.exists(cacheKey)) {
            return ME.redis.get(cacheKey);
        }
        //重新查询下角色授权
        ME.adminService.auth();
        return ME.redis.get(cacheKey);
    }




    /**
     * 根据用户ID获取用户名
     *
     * @param userId 用户ID
     * @return data
     */
    public static String getUserName(Long userId) {
        if (userId == null || userId == 0) {
            return "";
        }
        UserInfo userInfo = getUserInfo(userId);
        return Optional.ofNullable(userInfo).map(UserInfo::getRealname).orElse(null);
    }

    public static SimpleUser getSimpleUser(Long userId) {
        if (Objects.isNull(userId)) {
            return new SimpleUser();
        }
        SimpleUser simpleUser = handleSimpleUser(userId);
        if (Objects.isNull(simpleUser)) {
            simpleUser = new SimpleUser();
        }
        return simpleUser;
    }

    /**
     * 获取userList
     *
     * @param ids ids
     * @return java.util.List<com.kakarote.core.feign.admin.entity.SimpleUser>
     * @date 2021/11/19
     */
    public static List<SimpleUser> getSimpleUsers(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        List<SimpleUser> simpleUserList = new ArrayList<>(ids.size());
        ids.forEach(userId -> {
            SimpleUser simpleUser = getSimpleUser(userId);
            if (Objects.nonNull(simpleUser)) {
                simpleUserList.add(simpleUser);
            }
        });
        return simpleUserList;
    }

    /**
     * 根据ids查询用户真实名map
     *
     * @param ids ids
     * @return java.util.Map<java.lang.Long, java.lang.String>
     * @author jiao sir
     * @date 2021/11/19
     */
    public static Map<Long, String> getSimpleUserRealNameMap(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyMap();
        }
        Map<Long, String> usernameMap = new HashMap<>(ids.size());
        ids.forEach(userId -> {
            SimpleUser simpleUser = handleSimpleUser(userId);
            if (simpleUser != null) {
                usernameMap.put(simpleUser.getUserId(), simpleUser.getRealname());
            } else {
                usernameMap.put(userId, "");
            }
        });
        return usernameMap;
    }

    /**
     * 处理SimpleUser
     *
     * @param userId 用户id
     * @return simpleUser
     */
    private static SimpleUser handleSimpleUser(Long userId) {
        UserInfo userInfo = getUserInfo(userId);
        if (userInfo == null) {
            return null;
        }
        SimpleUser simpleUser = new SimpleUser();
        simpleUser.setUserId(userInfo.getUserId());
        simpleUser.setRealname(userInfo.getRealname());
        simpleUser.setDeptId(userInfo.getDeptId());
        simpleUser.setDeptName(userInfo.getDeptName());
        simpleUser.setWxUserId(userInfo.getWxUserId());
        simpleUser.setImg(userInfo.getImg());
        simpleUser.setStatus(userInfo.getStatus());
        return simpleUser;
    }

    /**
     * 根据部门ID获取部门名称，使用，号合并
     *
     * @param deptIds deptIds
     * @return data
     */
    public static <T> List<String> getDeptNameList(List<T> deptIds) {
        if (deptIds == null || deptIds.isEmpty()) {
            return Collections.emptyList();
        }
        List<String> stringList = new ArrayList<>(deptIds.size());
        for (T obj : deptIds) {
            String name = getDeptName(TypeUtils.castToLong(obj));
            if (!"".equals(name)) {
                stringList.add(name);
            }
        }
        return stringList;
    }

    /**
     * 根据部门ID获取部门名称
     *
     * @param deptId 部门ID
     * @return data
     */
    public static String getDeptName(Long deptId) {
        if (deptId == null) {
            return "";
        }
        return getDeptInfo(deptId).getName();
    }

    /**
     * 根据部门ID获取部门信息
     *
     * @param deptId 部门ID
     * @return data
     */
    public static SimpleDept getDeptInfo(Long deptId) {
        if (deptId == null) {
            return SimpleDept.emptyDept();
        }
        return ME.deptCache.computeIfAbsent(deptId, (CacheLoader<Long, SimpleDept>) key -> {
            List<SimpleDept> dept = ME.adminService.queryDeptByIds(Collections.singleton(deptId)).getData();
            if (dept == null || dept.isEmpty()) {
                return SimpleDept.emptyDept();
            }
            return dept.get(0);
        });
    }

    /**
     * 根据部门ID列表获取部门信息
     *
     * @param deptIds 部门ID列表
     * @return data
     */
    public static List<SimpleDept> getDeptList(Collection<?> deptIds) {
        if (deptIds == null || deptIds.isEmpty()) {
            return Collections.emptyList();
        }
        List<SimpleDept> simpleDeptList = new ArrayList<>(deptIds.size());
        for (Object deptId : deptIds) {
            SimpleDept simpleDept = getDeptInfo(TypeUtils.castToLong(deptId));
            if (simpleDept != null) {
                simpleDeptList.add(simpleDept);
            }
        }
        return simpleDeptList;
    }

    /**
     * 查询该用户下级的用户
     *
     * @param userId 用户ID 0代表全部
     * @return data
     */
    public static List<Long> queryChildUserId(Long userId) {
        return ME.adminService.queryChildUserId(userId).getData();
    }

    /**
     * 查询部门下属部门
     *
     * @param deptId 上级ID
     * @return data
     */
    public static List<Long> queryChildDeptId(Long deptId) {
        return ME.adminService.queryChildDeptId(deptId).getData();
    }


    /**
     * 删除部门缓存
     *
     * @param deptId 部门ID
     */
    public static void removeDeptCache(Long deptId) {
        ME.deptCache.remove(deptId);
    }

    /**
     * 删除用户缓存
     *
     * @param userId 用户ID
     */
    public static void removeUserCache(Long userId) {
        ME.userCache.remove(userId);
    }

    /**
     * 添加用户缓存
     */
    public static void putUserCache(UserInfo userInfo) {
        ME.userCache.put(userInfo.getUserId(), userInfo);
    }

    /**
     * 获取企业状态
     *
     * @param companyId 企业ID
     * @return true为正常
     */
    public static Boolean getCompanyStatus(Long companyId) {
        return ME.companyCache.get(companyId);
    }

    /**
     * 设置企业状态
     *
     * @param companyId     企业ID
     * @param companyStatus 企业状态
     */
    public static void putCompanyStatus(Long companyId, Boolean companyStatus) {
        ME.companyCache.put(companyId, companyStatus);
    }

    /**
     * 删除企业状态
     *
     * @param companyId 企业ID
     */
    public static void removeCompanyStatus(Long companyId) {
        ME.companyCache.remove(companyId);
    }

}
